home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 12 / Cream of the Crop 12 (Part II) / Cream of the Crop 12 (Part II).iso / OS2 / V15N04.ZIP / WARPCA.ZIP / WCABSRC.ZIP / DO_DRAG.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-01-18  |  20.7 KB  |  685 lines

  1. // DO_DRAG.CPP  -- Drag API functions to allow dragging files from Warp Cabinet to other
  2. //                          system objects that accept files.
  3. #define INCL_DOSFILEMGR
  4. #define INCL_DOSPROCESS
  5. #define INCL_DOSERRORS
  6. #define INCL_SHLERRORS
  7. #define INCL_WIN
  8. #define INCL_WINSTDDRAG
  9. #define INCL_WINDIALOGS
  10.  
  11. #include <os2.h>
  12. #include <string.h>
  13. #include <process.h>
  14. #include <classlib\arrays.h>
  15. #include "filentry.h"
  16. #include "resource.h"
  17.  
  18. typedef char *LPSTR;
  19.  
  20. #include "do_drag.h"
  21.  
  22. // Complete list of selected files is in WARPFILE.CPP
  23. static PDRAGTARGETTHREAD vpThreadParms = NULL;
  24.  
  25. // Globals for this module.
  26. static char   szRendMechFmtFILE []  = "<DRM_OS2FILE,DRF_UNKNOWN>";
  27. static USHORT    usOperation;  // Stores user operation.
  28. static ULONG    ulDragCount = 0L;  // Number of drag operations.
  29. static PDRAGINFO pGlobalDraginfo = NULL;
  30.  
  31. static HAB   habGlobal;
  32. static CHAR  szClientClass[12];        // "DragDrop"
  33. static HWND  hwndClient;               // Needed by change dir. function
  34. static HWND  hwndGlobalFileList;       // Handle to list control..
  35.  
  36. static HPOINTER hptrBusy;              // Mouse Pointer to show when a
  37.                                                     // drag is in progress
  38.  
  39. // Cleans-up all resources needed for a drag operation.
  40. BOOL FreeSourceResources (HAB hab, PDRAGINFO pDraginfo)
  41. {
  42.     PDRAGITEM       pDragitem;
  43.     ULONG           ulItemsDragged, i;
  44.  
  45.     if(!DrgAccessDraginfo(pDraginfo) && DrgDeleteDraginfoStrHandles(pDraginfo))
  46.     {
  47.         // Drag access not OK.
  48.         MessageBox(HWND_DESKTOP, IDMSG_DRAGACCESSERROR, MB_OK | MB_ERROR, TRUE);
  49.         return FALSE;
  50.     }
  51.  
  52.     if(DrgFreeDraginfo(pDraginfo)
  53.                     || PMERR_SOURCE_SAME_AS_TARGET == WinGetLastError(hab))
  54.         return TRUE;
  55.     else
  56.     {
  57.         MessageBox(HWND_DESKTOP, IDMSG_DRAGFREEERROR, MB_OK | MB_ERROR, TRUE);
  58.         return FALSE;
  59.     }
  60. }
  61.  
  62. // Prevents our app. from closing during a drag operation.
  63. VOID PreventClose(HWND hwndClient, ULONG cDrag)
  64. {
  65.     HWND hwndSysMenu = WinWindowFromID(ParentOf(hwndClient), FID_SYSMENU);
  66.     WinSendMsg(hwndSysMenu, MM_SETITEMATTR, MPFROM2SHORT(SC_CLOSE, (SHORT)TRUE),
  67.                  MPFROM2SHORT(MIA_DISABLED, (SHORT)(cDrag ? MIA_DISABLED : FALSE)));
  68.     return;
  69. }
  70.  
  71. // Removes final backslash from an OS/2 directory.
  72. VOID RemoveFinalBackslash (PSZ p)
  73. {
  74.     for (; *p; ++p);  // Go to the end of the string.
  75.     if (*--p == '\\')
  76.     {
  77.         *p = '\0';
  78.     }
  79. }
  80.  
  81. // Starts the drag operation.
  82. BOOL InitDrag (HAB hab, HWND hwndClient,  int nFilesToDrag, HPOINTER hptrFile,
  83.                     HPOINTER hptrFolder, HPOINTER hptrMulti, LPSTR pContainerName)
  84. {
  85.     CHAR             chDrive;
  86.     SHORT            item;
  87.     ULONG            i;
  88.     ULONG               ulItemsDragged = nFilesToDrag;
  89.     HWND             hwndTarget;
  90.     LHANDLE          hImage;
  91.     DRAGITEM         Dragitem;
  92.     HSTR             hstrType, hstrRMF, hstrContainerName;
  93.     USHORT           fsControl;
  94.     USHORT           fsSupportedOps;
  95.     CHAR             szItemName [64];
  96.     CHAR             szFullContainerName [CCHMAXPATH];
  97.     PDRAGINFO        pSourceDraginfo;
  98.     DRAGIMAGE        dimg;
  99.  
  100.     PDRAGINFO pdinfo;       // Pointer to DRAGINFO structure
  101.     HWND      hwnd;         // Handle of calling (source) window
  102.     BOOL      flResult;     // Result indicator
  103.     DRAGITEM  ditem;        // DRAGITEM structure
  104.     HBITMAP   hbm;          // Bit-map handle
  105.     HWND      hwndDrop;     // Handle of drop (target) window
  106.  
  107.     habGlobal = hab;
  108.  
  109.     LONG lDragButton;
  110.  
  111.     // Get number of items to drag.
  112.     if(!nFilesToDrag)
  113.     {
  114.         MessageBox(HWND_DESKTOP, IDMSG_ATLEASTONE, MB_OK | MB_ERROR, TRUE);
  115.         return FALSE;
  116.     }
  117.  
  118.     // Allocate the DRAGINFO structure and the APPDRAGINFO structure.
  119.     pSourceDraginfo = DrgAllocDraginfo(nFilesToDrag);
  120.  
  121.     // Save to global handle.
  122.     pGlobalDraginfo = pSourceDraginfo;
  123.  
  124.     // Initialize variable used to initialize the internal DRAGITEM
  125.     // structure.
  126.     hstrType  = DrgAddStrHandle ((PSZ)DRT_UNKNOWN);       // File type is unknown
  127.     hstrRMF   = DrgAddStrHandle ((PSZ)szRendMechFmtFILE); // os2file, unknown
  128.     strcpy (szFullContainerName, (char*)pContainerName);  // container name  
  129.  
  130.     RemoveFinalBackslash ((PSZ)szFullContainerName);
  131.     strcat (szFullContainerName, "\\");
  132.     hstrContainerName = DrgAddStrHandle((PSZ)szFullContainerName);
  133.  
  134.     fsControl = 0;
  135.     chDrive = (CHAR) pContainerName[0];
  136.  
  137.     if((chDrive=='A') || (chDrive=='B') || (chDrive=='a') || (chDrive=='b'))
  138.     {
  139.         // Is source container removable media?
  140.         fsControl = (SHORT)(fsControl | ((SHORT)DC_REMOVEABLEMEDIA));
  141.     }
  142.  
  143.     fsSupportedOps = DO_COPYABLE | DO_MOVEABLE;    // Can only move or copy.
  144.  
  145.     // Initialize common portions of the internal Dragitem buffer.
  146.     Dragitem.hwndItem          = hwndClient;
  147.     Dragitem.hstrType          = hstrType;
  148.     Dragitem.hstrRMF           = hstrRMF;
  149.     Dragitem.hstrContainerName = hstrContainerName;
  150.     Dragitem.fsControl         = fsControl;
  151.     Dragitem.fsSupportedOps    = fsSupportedOps;
  152.  
  153.     // Write selected files/dirs. to OS/2.
  154.     FILEENTRY *pFileEntry;
  155.  
  156.     for (i = 0L; i < nFilesToDrag; i++)
  157.     {
  158.         pFileEntry = (FILEENTRY *)SelectedFileList[i];
  159.         if(!pFileEntry)
  160.             continue;
  161.  
  162.         Dragitem.hstrSourceName = DrgAddStrHandle ((PSZ)pFileEntry->szFileName);
  163.         Dragitem.hstrTargetName = Dragitem.hstrSourceName;
  164.  
  165.         Dragitem.ulItemID = i;
  166.         if (pFileEntry->nType == 1)
  167.             Dragitem.fsControl = (SHORT)((Dragitem.fsControl | ((SHORT)DC_CONTAINER)));
  168.  
  169.         if(!DrgSetDragitem(pSourceDraginfo, &Dragitem, sizeof(DRAGITEM), i))
  170.         {
  171.             MessageBox(HWND_DESKTOP, IDMSG_DRAGSETITEMERROR, MB_OK | MB_ERROR, TRUE);
  172.             return FALSE;
  173.         }
  174.     }
  175.     //  Drag the items.
  176.     if (ulItemsDragged == 1L)
  177.         hImage = (Dragitem.fsControl & DC_CONTAINER) ? hptrFolder : hptrFile;
  178.     else
  179.         hImage = hptrMulti;
  180.  
  181.     ++ulDragCount;                     // Remember drag is in progress
  182.     PreventClose(hwndClient, ulDragCount);
  183.  
  184.     dimg.cb       = sizeof (DRAGIMAGE);
  185.     dimg.hImage   = hImage;
  186.     dimg.fl       = DRG_ICON;
  187.     dimg.cxOffset = 0;
  188.     dimg.cyOffset = 0;
  189.  
  190.     pSourceDraginfo->hwndSource = hwndClient;
  191.  
  192.     // End drag when either left or right button is released.
  193.     lDragButton = bDragLeftBtn ? VK_BUTTON1 : VK_BUTTON2;
  194.  
  195.     hwndTarget = DrgDrag(hwndClient, pSourceDraginfo, &dimg, 1L, lDragButton, NULL);
  196.  
  197.     // User cancelled the drag or asked for help, so we can release
  198.     // the resources allocated to the drag operation.    --ulDragCount;
  199.     PreventClose (hwndClient, ulDragCount);
  200.     if (hwndTarget == NULLHANDLE)
  201.         return FALSE;
  202.     else
  203.         return TRUE;// Turn off 'pAppDraginfo' is assigned a value that is never used warning.
  204. #pragma warn -aus
  205. }
  206. #pragma warn +aus
  207.  
  208. MRESULT EndConversation(HAB hab, HWND hwndClient, MPARAM mp1, MPARAM mp2)
  209. {
  210.     USHORT i;
  211.     // Did the target properly render the item?
  212.     if(mp2 == (MPARAM)DMFL_TARGETFAIL)
  213.         MessageBox(HWND_DESKTOP, IDMSG_TARGETRENDER, MB_OK | MB_ERROR, TRUE);
  214.     // Refresh our listbox.
  215.     WinSendMsg(hwndGlobalParent, CM_REFRESH, 0, 0);
  216.  
  217.     if(DrgFreeDraginfo(pGlobalDraginfo)
  218.         || PMERR_SOURCE_SAME_AS_TARGET == WinGetLastError(hab))
  219.     {
  220.         --ulDragCount;                   // Indicate drag completed.
  221.         PreventClose(hwndClient, ulDragCount);
  222.     }
  223.     else
  224.         MessageBox(HWND_DESKTOP, IDMSG_DRAGFREEERROR, MB_OK | MB_ERROR, TRUE);
  225.     mp1; // Kill warning.
  226.     return (MRESULT)NULL;
  227. }
  228.  
  229. MRESULT DragLeave (void)
  230. {
  231.     return (MRESULT)NULL;
  232. }
  233.  
  234. // Displays help message for dragging files.
  235. MRESULT DropHelp (HWND hwndClient, MPARAM mp1)
  236. {
  237.     PDRAGINFO pDraginfo = (PDRAGINFO)mp1;
  238.  
  239.     char message[81];
  240.  
  241.     if(!DrgAccessDraginfo (pDraginfo))
  242.     {
  243.         MessageBox(HWND_DESKTOP, IDMSG_DRAGACCESSERROR, MB_OK | MB_ERROR, TRUE);
  244.     }
  245.     strcpy (message, "Dropping here would perform ");
  246.  
  247.     switch (pDraginfo->usOperation)
  248.     {
  249.         case DO_DEFAULT:
  250.             strcat (message, "the default ");
  251.             break;
  252.         case DO_COPY:
  253.             strcat (message, "a copy ");
  254.             break;
  255.         case DO_MOVE:
  256.             strcat (message, "a move ");
  257.             break;
  258.         case DO_UNKNOWN:
  259.             strcat (message, "an unknown (private) ");
  260.             break;
  261.     }
  262.     strcat (message, "operation.");
  263.     Message ((PSZ)message);
  264.  
  265.     if(DrgDeleteDraginfoStrHandles(pDraginfo) && DrgFreeDraginfo(pDraginfo));
  266.     else
  267.     {
  268.         MessageBox(HWND_DESKTOP, IDMSG_DRAGERROR, MB_OK | MB_ERROR, TRUE);
  269.     }
  270.     return (MRESULT)NULL;
  271. // turn off warnings for unreferenced formal parameters.
  272. #pragma warn -par
  273. }
  274. #pragma warn +par
  275.  
  276. // Provides visual feedback for dragging over this object.
  277. MRESULT DragOver(HAB hab, MPARAM mp1, LPSTR pCurrentDir)
  278. {
  279.     PDRAGINFO pDraginfo = (PDRAGINFO)mp1;
  280.     USHORT        usIndicator, cItems, i;
  281.     ULONG         ulBytesWritten;
  282.     PDRAGITEM     pditem;
  283.     CHAR          SourceDir [CCHMAXPATH], chDrive;
  284.  
  285.     // Get access to the DRAGINFO structure.
  286.     if(!DrgAccessDraginfo(pDraginfo))
  287.     {
  288.         MessageBox(HWND_DESKTOP, IDMSG_DRAGACCESSERROR, MB_OK | MB_ERROR, TRUE);
  289.         return (MRFROM2SHORT (DOR_NODROPOP, 0));
  290.     }
  291.     usOperation = (USHORT)DO_MOVE;          // the default operation is move
  292.  
  293.     // Determine if a drop can be accepted.
  294.     switch (pDraginfo->usOperation)
  295.     {
  296.         // return DOR_NODROPOP if current operation is link or unknown.
  297.  
  298.         case DO_UNKNOWN:
  299.             if(!DrgFreeDraginfo (pDraginfo))
  300.                 MessageBox(HWND_DESKTOP, IDMSG_DRAGFREEERROR, MB_OK | MB_ERROR, TRUE);
  301.             return (MRFROM2SHORT (DOR_NODROPOP, 0));
  302.  
  303.  
  304.         // Determine default operation if current operation is default.
  305.         // The default is move unless either the source or the target is
  306.         // on different removable media.
  307.         case DO_DEFAULT:
  308.             pditem = DrgQueryDragitemPtr (pDraginfo, 0);
  309.             ulBytesWritten = DrgQueryStrName(pditem->hstrContainerName,
  310.                                                     sizeof(SourceDir),
  311.                                                     (PSZ)SourceDir);
  312.             if(ulBytesWritten == 0L)
  313.             {
  314.                 MessageBox(HWND_DESKTOP, IDMSG_DRAGQUERYSTRINGERROR,
  315.                                       MB_OK | MB_ERROR, TRUE);
  316.                 return (MRFROM2SHORT (DOR_NODROPOP, 0));
  317.             }
  318.  
  319.             // If the source and target are on the
  320.             // same drive, the operation is a move
  321.             //
  322.             if (*pCurrentDir == SourceDir[0])
  323.                 usOperation = (USHORT)DO_MOVE;
  324.                 // Otherwise, different drives
  325.             else
  326.             {
  327.                 chDrive = (CHAR)pCurrentDir[0];
  328.                 // If the target is A: or B:, or the source
  329.                 // is removeable media, the operation is a copy
  330.                 if((chDrive == 'A') || (chDrive == 'B') || (chDrive == 'a') ||
  331.                     (chDrive=='b') || pditem->fsControl & DC_REMOVEABLEMEDIA)
  332.                 {
  333.                     usOperation = (USHORT)DO_COPY;
  334.                 }
  335.                 // Otherwise, the default operation is a move
  336.                 else
  337.                 {
  338.                     usOperation = (USHORT)DO_MOVE;
  339.                 }
  340.             }
  341.             break;
  342.  
  343.         case DO_MOVE:
  344.         case DO_COPY:
  345.             usOperation = pDraginfo->usOperation;
  346.             break;
  347.     }
  348.  
  349.     // In order to support the operation, the source must support the
  350.     // operation this target has decided upon.  The source must also
  351.     // support a rendering mechanism of <DRM_OS2FILE,DRF_UNKNOWN>.
  352.     // This target doesn't care about the file type since we are copying the file only.
  353.     usIndicator = DOR_DROP;
  354.     cItems = (SHORT)DrgQueryDragitemCount (pDraginfo);
  355.  
  356.     // Inspect each item to see if it is acceptable.
  357.     for (i = 0; i < cItems; ++i)
  358.     {
  359.         pditem = DrgQueryDragitemPtr (pDraginfo, i);
  360.  
  361.         // The item is acceptable only if it is copyable and the
  362.         // operation is a copy, or it is moveable and the operation
  363.         // is a move, and it can render <DRM_OS2FILE,DRF_UNKNOWN>
  364.         if (((pditem->fsSupportedOps & DO_COPYABLE) &&
  365.                                 (usOperation == (USHORT)DO_COPY)) ||
  366.              ((pditem->fsSupportedOps & DO_MOVEABLE) &&
  367.                                   (usOperation == (USHORT)DO_MOVE)))
  368.         {
  369.             if (DrgVerifyRMF(pditem, (PSZ)"DRM_OS2FILE", (PSZ)"DRF_UNKNOWN"))
  370.             {
  371.                 usIndicator = DOR_DROP;
  372.             }
  373.             else
  374.             {
  375.                 usIndicator = DOR_NEVERDROP;
  376.                 break;
  377.             }
  378.         }
  379.         else
  380.         {
  381.             usIndicator = DOR_NODROPOP;
  382.             break;
  383.         }
  384.     }
  385.  
  386.     if(!DrgFreeDraginfo(pDraginfo))
  387.         if(PMERR_SOURCE_SAME_AS_TARGET != WinGetLastError(hab))
  388.         {
  389.             MessageBox(HWND_DESKTOP, IDMSG_DRAGFREEERROR, MB_OK | MB_ERROR, TRUE);
  390.             return (MRFROM2SHORT (DOR_NODROPOP, 0));
  391.         }
  392.     return (MRFROM2SHORT(usIndicator, usOperation));
  393. }
  394.  
  395. MRESULT Drop(HAB hab, HWND hwndClient, MPARAM mp1, LPSTR pCurrentDir)
  396. {
  397.     PDRAGINFO pDraginfo = (PDRAGINFO)mp1;
  398.     PDRAGTARGETTHREAD     pParm;
  399.     PBYTE          aStack;
  400.     TID           tid;
  401.     USHORT        i;
  402.     PDRAGTRANSFER pdxfer;
  403.     PDRAGITEM     pditem;
  404.     HSTR          hstrRMF;
  405.     char          szFullTargetName  [CCHMAXPATH];
  406.     char          szTargetFile [CCHMAXPATHCOMP];
  407.     QMSG          qmsg;
  408.     USHORT        cRetry, idTimer;
  409.     ULONG         mr, ulBytesWritten;
  410.  
  411.     // Get access to the Draginfo structure.
  412.     if(!DrgAccessDraginfo (pDraginfo))
  413.         MessageBox(HWND_DESKTOP, IDMSG_DRAGACCESSERROR, MB_OK | MB_ERROR, TRUE);
  414.     if (pDraginfo->hwndSource == hwndClient)
  415.     {
  416.         // Source window and target window are the same, so don't do the
  417.         // operation... just release the resources allocated for the drag.
  418.         FreeSourceResources (hab, pDraginfo);
  419.         --ulDragCount;
  420.         PreventClose (hwndClient, ulDragCount);
  421.         return (MRESULT)NULL;
  422.     }
  423.  
  424.     pditem = DrgQueryDragitemPtr (pDraginfo, 0);
  425.  
  426.     // If the source name wasn't provided, let the source render
  427.     if (!pditem->hstrSourceName)
  428.     {
  429.         pdxfer   = DrgAllocDragtransfer (pDraginfo->cditem);
  430.         hstrRMF  = DrgAddStrHandle ((PSZ)"<DRM_OS2FILE, DRF_UNKNOWN>");
  431.  
  432.         for (i=0; i<pDraginfo->cditem; i++)
  433.         {
  434.             pditem = DrgQueryDragitemPtr (pDraginfo, i);
  435.  
  436.             // Build the fully qualified target file name.
  437.             strcpy (szFullTargetName, (char*)pCurrentDir);
  438.             RemoveFinalBackslash ((PSZ)szFullTargetName);
  439.             ulBytesWritten =DrgQueryStrName(pditem->hstrTargetName,
  440.                                                       sizeof(szTargetFile),
  441.                                                       (PSZ)szTargetFile);
  442.             if(ulBytesWritten == 0L)
  443.                 MessageBox(HWND_DESKTOP, IDMSG_DRAGQUERYSTRINGERROR,
  444.                                     MB_OK | MB_ERROR, TRUE);
  445.  
  446.             if (szTargetFile[0] != '\\')
  447.                 strcat(szFullTargetName, "\\");
  448.             strcat(szFullTargetName, szTargetFile);
  449.  
  450.             // Initialize the DRAGTRANSFER structure.
  451.             pdxfer[i].cb               = sizeof (DRAGTRANSFER);
  452.             pdxfer[i].hwndClient       = hwndClient;
  453.             pdxfer[i].pditem           = pditem;
  454.             pdxfer[i].hstrSelectedRMF  = hstrRMF;
  455.             pdxfer[i].hstrRenderToName = DrgAddStrHandle ((PSZ)szFullTargetName);
  456.             pdxfer[i].ulTargetInfo     = 0L;
  457.             pdxfer[i].usOperation      = pDraginfo->usOperation;
  458.             pdxfer[i].fsReply          = 0;
  459.  
  460.             // Send the DM_RENDER to the source, retrying as necessary
  461.             for (cRetry=0, mr=0; cRetry<MAX_RETRIES && !mr; cRetry++)
  462.             {
  463.                 mr = (ULONG)DrgSendTransferMsg(pDraginfo->hwndSource,
  464.                                                          DM_RENDER,
  465.                                                          (MPARAM)(pdxfer + i),
  466.                                                          (MPARAM)NULL);
  467.                 //  If the source didn't render, retry if we can
  468.                 if (!mr)
  469.                 {
  470.                     if (pdxfer[i].fsReply & DMFL_RENDERRETRY)
  471.                     {
  472.                         idTimer = (USHORT)WinStartTimer (0L, 0L, 0L, 1000L);
  473.  
  474.                         // Start a timer to wait, but process
  475.                         // messages so we don't hang the queue
  476.                         while (WinGetMsg (0L, &qmsg, 0L, 0, 0))
  477.                         {
  478.                             if ((qmsg.msg == WM_TIMER) &&
  479.                                          ((USHORT) qmsg.mp1 == idTimer))
  480.                             {
  481.                                 WinStopTimer (0L, 0L, idTimer);
  482.                                 break;
  483.                             }
  484.                             else
  485.                                 WinDispatchMsg (0L, &qmsg);
  486.                         }
  487.                     }
  488.                     else
  489.                         DrgFreeDragtransfer(pdxfer + i);
  490.                 }
  491.             }
  492.         }
  493.     }
  494.     // Allocate the stack segment for the target thread.
  495.     else if (DosGetNamedSharedMem((PPVOID)&aStack, (PSZ)"\\sharemem\\dragmem",
  496.                                             PAG_READ | PAG_WRITE) != 0LU)
  497.     {
  498.         MessageBox(HWND_DESKTOP, IDMSG_CANTCREATESTACK, MB_OK | MB_ERROR, TRUE);
  499.         DrgDeleteDraginfoStrHandles(pDraginfo);
  500.         DrgFreeDraginfo(pDraginfo);
  501.     }
  502.     else
  503.     {
  504.         // Build the parameter list structure for the target thread.
  505.         DosSubAllocMem(aStack, (PPVOID)&pParm, sizeof(DRAGTARGETTHREAD));
  506.  
  507.         pParm->pDraginfo   = pDraginfo;
  508.         pParm->hwndClient  = hwndClient;
  509.         pParm->usOperation = usOperation;
  510.         strcpy(pParm->szTargetDir, (char*)pCurrentDir);
  511.  
  512.         // Remember that a drag is in progress and start the target thread.
  513.         ++ulDragCount;
  514.         PreventClose (hwndClient, ulDragCount);
  515.  
  516.         vpThreadParms = pParm;
  517.  
  518.         _beginthread(TargetThread, STACKSIZE, (void *)vpThreadParms);
  519.     }
  520.     return (MRESULT)NULL;
  521. }
  522.  
  523.  
  524. // Clean-up.
  525. MRESULT EndTarget (HWND hwnd, PDRAGTARGETTHREAD pParm)
  526. {
  527.     USHORT                cItems, i;
  528.     DRAGITEM              Dragitem;
  529.  
  530.     // Decrement the count of drag operations in progress and prepare to
  531.     // release the resources allocated for the drag operation.
  532.     --ulDragCount;
  533.     PreventClose (hwnd, ulDragCount);
  534.     cItems = (SHORT)DrgQueryDragitemCount (pParm->pDraginfo);
  535.  
  536.     // End the conversation for each item in the DRAGINFO structure and
  537.     // let source know we have completed the drag operation for each item.
  538.     for (i = 0; i < cItems; ++i)
  539.     {
  540.         if(!DrgQueryDragitem (pParm->pDraginfo, sizeof(Dragitem), &Dragitem, i))
  541.             MessageBox(HWND_DESKTOP, IDMSG_DRAGQUERYITEMERROR,
  542.                           MB_OK | MB_ERROR, TRUE);
  543.         DrgSendTransferMsg(Dragitem.hwndItem, DM_ENDCONVERSATION,
  544.                                  MPFROMLONG(Dragitem.ulItemID),
  545.                                  MPFROMLONG(DMFL_TARGETSUCCESSFUL));
  546.     }
  547.     // Free the draginfo structure.
  548.     if(DrgDeleteDraginfoStrHandles(pParm->pDraginfo)
  549.                       && DrgFreeDraginfo(pParm->pDraginfo));
  550.     else
  551.         MessageBox(HWND_DESKTOP, IDMSG_DRAGERROR, MB_OK | MB_ERROR, TRUE);
  552.     WinPostMsg(hwndGlobalParent, CM_REFRESH, NULL, NULL);
  553.     return (MRESULT)NULL;
  554. }
  555.  
  556. BOOL CheckBusy (void)
  557. {
  558.     return ((BOOL) ulDragCount);
  559. }
  560.  
  561. MRESULT CheckClose (HWND hwnd)
  562. {
  563.     if (!ulDragCount)
  564.         WinPostMsg (hwnd, WM_QUIT, (MPARAM)0L, (MPARAM)0L);
  565.  
  566.     return ((MPARAM)NULL);
  567. }
  568.  
  569. void TargetThread (void *pDummy)
  570. {
  571.     PDRAGTARGETTHREAD pParm;
  572.     USHORT        cItems, i;
  573.     ULONG         ulBytesWritten;
  574.     DRAGITEM      Dragitem;
  575.     char          szFullSourceName  [CCHMAXPATH];
  576.     char          szFullTargetName  [CCHMAXPATH];
  577.     char          szSourceFile [CCHMAXPATHCOMP];
  578.     char          szTargetFile [CCHMAXPATHCOMP];
  579.  
  580.     pDummy; // Kill warning.
  581.  
  582.     pParm = vpThreadParms;
  583.  
  584.     // Get the number of items being dragged.
  585.     cItems = (SHORT)DrgQueryDragitemCount (pParm->pDraginfo);
  586.  
  587.     // If the source has provided the file name in the DRAGITEM
  588.     // structures, we can go ahead and do a target copy without getting
  589.     // the source involved in the operation.  We will always copy the file
  590.     // using the suggested target name.  In this application the names
  591.     // are always the same.
  592.     for (i = 0; i < cItems; ++i)
  593.     {
  594.         if(!DrgQueryDragitem (pParm->pDraginfo, sizeof(Dragitem), &Dragitem, i))
  595.             MessageBox(HWND_DESKTOP, IDMSG_DRAGQUERYITEMERROR,
  596.                              MB_OK | MB_ERROR, TRUE);
  597.         if(Dragitem.hstrSourceName    != 0L &&
  598.             Dragitem.hstrTargetName    != 0L &&
  599.             Dragitem.hstrContainerName != 0L)
  600.         {
  601.             // Build the fully qualified source file name.
  602.             ulBytesWritten = DrgQueryStrName(Dragitem.hstrContainerName,
  603.                                                         sizeof(szFullSourceName),
  604.                                                         (PSZ)szFullSourceName);
  605.             if(ulBytesWritten == 0)
  606.                 MessageBox(HWND_DESKTOP, IDMSG_DRAGQUERYSTRINGERROR,
  607.                               MB_OK | MB_ERROR, TRUE);
  608.             ulBytesWritten = DrgQueryStrName(Dragitem.hstrSourceName,
  609.                                                         sizeof(szSourceFile),
  610.                                                         (PSZ)szSourceFile);
  611.             if(ulBytesWritten == 0)
  612.                 MessageBox(HWND_DESKTOP, IDMSG_DRAGQUERYSTRINGERROR,
  613.                                 MB_OK | MB_ERROR, TRUE);
  614.  
  615.             if (szSourceFile[0] == '\\')
  616.                 strcpy (szSourceFile, szSourceFile+1);
  617.  
  618.             strcat (szFullSourceName, szSourceFile);
  619.  
  620.             // Build the fully qualified target file name.
  621.             strcpy (szFullTargetName, pParm->szTargetDir);
  622.             RemoveFinalBackslash ((PSZ)szFullTargetName);
  623.             ulBytesWritten = DrgQueryStrName(Dragitem.hstrTargetName,
  624.                                                         sizeof(szTargetFile),
  625.                                                         (PSZ)szTargetFile);
  626.             if(ulBytesWritten == 0)
  627.                 MessageBox(HWND_DESKTOP, IDMSG_DRAGQUERYSTRINGERROR,
  628.                                     MB_OK | MB_ERROR, TRUE);
  629.  
  630.             if (szTargetFile[0] != '\\')
  631.                 strcat (szFullTargetName, "\\");
  632.  
  633.             strcat (szFullTargetName, szTargetFile);
  634.  
  635.             // Do the operation.  DosCopy works with different drives;
  636.             // DosMove does not, so we will use DosCopy and DosDelete.
  637.             switch (pParm->usOperation)
  638.             {
  639.                 case DO_MOVE:     //  Mimic DosMove with DosCopy and DosDelete.
  640.                      if(DosCopy((PSZ)szFullSourceName, (PSZ)szFullTargetName, DCPY_EXISTING)
  641.                                       == NO_ERROR)
  642.                          DosDelete((PSZ)szFullSourceName);
  643.                      break;
  644.                 case DO_COPY:
  645.                      DosCopy ((PSZ)szFullSourceName, (PSZ)szFullTargetName, DCPY_EXISTING);
  646.                      break;
  647.             }
  648.         }
  649.     }
  650.  
  651.     // Post ourselves a target complete message so the client window
  652.     // knows we are done and can free the stack segment and the draginfo
  653.     // structure.
  654.     DosEnterCritSec();                   // Make sure we finish before the
  655.                                                      // main thread frees our stack.
  656.     WinPostMsg (pParm->hwndClient, WM_TARGETCOMPLETE, pParm, NULL);
  657. }
  658.  
  659. VOID Message (PSZ pszMsg)
  660. {
  661.     WinMessageBox (HWND_DESKTOP, hwndClient, pszMsg, (PSZ)szClientClass, 0,
  662.                       MB_MOVEABLE | MB_ICONEXCLAMATION);
  663. }
  664.  
  665. SHORT MessageBox(HWND hwndOwner,
  666.                       SHORT idMsg,
  667.                       SHORT fsStyle,
  668.                       BOOL fBeep)
  669. {
  670.     CHAR szText[MESSAGELEN];
  671.  
  672.     if(!WinLoadMessage(habGlobal, (HMODULE)0L, idMsg, MESSAGELEN, (PSZ)szText))
  673.     {
  674.          WinAlarm(HWND_DESKTOP, WA_ERROR);
  675.          return MBID_ERROR;
  676.     }
  677.  
  678.     if(fBeep)
  679.          WinAlarm(HWND_DESKTOP, WA_ERROR);
  680.  
  681.     return (SHORT)(WinMessageBox(HWND_DESKTOP, hwndOwner,(PSZ)szText,(PSZ)NULL,
  682.                       (USHORT)MSGBOXID,(ULONG)fsStyle));
  683. }
  684.  
  685.